﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../global/head.h"
#include "json_impl.h"
#include "mgr_impl.h"

////////////////////////////////////////////////////////////////////////////////////////////
// 

namespace xos_json
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    mgr_impl::mgr_impl()
    {
    }

    mgr_impl::~mgr_impl()
    {
        if( g_pSysData )
        {
            g_pSysData->term();
            delete g_pSysData;
            g_pSysData = 0;
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // xos_box::i_property -> i_json
    // 

    int mgr_impl::prop_to_json( xos_box::i_property * pProperty, char * lpszJson, int nSize, int * pnLenRet )
    {
        int ret = 0;

        i_json * pJson = 0;

        if( 0 == ret )
        {
            ret = prop_to_json( pProperty, &pJson );
        }

        if( 0 == ret )
        {
            ret = pack( pJson, lpszJson, nSize, pnLenRet );
        }

        xos_stl::release_interface( pJson );

        return ret;
    }

    int mgr_impl::prop_to_json( xos_box::i_property * pProperty, i_json ** ppv )
    {
        int ret = 0;

        i_json * pJson = 0;

        if( 0 == ret )
        {
            ret = create( &pJson );
        }

        if( 0 == ret )
        {
            ret = prop_to_json( pProperty, pJson );
        }

        if( ( 0 == ret ) && ppv )
        {
            *ppv = pJson;
            pJson = 0;
        }

        xos_stl::release_interface( pJson );

        return ret;
    }

    int mgr_impl::prop_to_json( xos_box::i_property * pProperty, i_json * pRoot )
    {
        int ret = 0;

        xos_box::i_variant * pVT = 0;
        const char * lpszKey = 0;

        for( pProperty->reset(); ( pVT = pProperty->name_data( &lpszKey, 0, 0, 0 ) ); pProperty->name_next() )
        {
            xos_box::i_variant::VT_TYPE vType = pVT->get_type( 0 );
            switch( vType )
            {
            case xos_box::i_variant::VT_STRING:
                {
                    pRoot->set_str( lpszKey, pVT->str() );
                }
                break;
            case xos_box::i_variant::VT_DOUBLE:
                {
                    pRoot->set_double( lpszKey, pVT->dbl() );
                }
                break;
            case xos_box::i_variant::VT_FLOAT:
                {
                    pRoot->set_double( lpszKey, pVT->flt() );
                }
                break;
            case xos_box::i_variant::VT_INT:
                {
                    pRoot->set_int( lpszKey, pVT->it() );
                }
                break;
            case xos_box::i_variant::VT_OBJECT:
                {
                    obj_to_json( lpszKey, pVT, pRoot );
                }
                break;
            default:
                {
                    pRoot->set_str( lpszKey, "unknown" );
                }
                break;
            }
        }

        return ret;
    }

    int mgr_impl::obj_to_json( const char * lpszKey, xos_box::i_variant * pVT, i_json * pRoot )
    {
        int result = 0;
        int ret = 0;

        if( ( 0 == ret ) && !pVT )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            xos_box::i_property * pProperty = pVT->prop( 0 );
            if( pProperty )
            {
                helper_prop_to_json( lpszKey, pProperty, pRoot );
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            xos_box::i_list * pList = pVT->list( 0 );
            if( pList )
            {
                helper_list_to_json( lpszKey, pList, pRoot );
                ret = 1;
            }
        }

        return result;
    }

    int mgr_impl::helper_prop_to_json( const char * lpszKey, xos_box::i_property * pProperty, i_json * pRoot )
    {
        int ret = 0;

        i_json * pJson = 0;

        if( 0 == ret )
        {
            ret = create( &pJson );
        }

        if( 0 == ret )
        {
            prop_to_json( pProperty, pJson );
        }

        if( 0 == ret )
        {
            pRoot->set_json( lpszKey, pJson );
        }

        xos_stl::release_interface( pJson );

        return ret;
    }

    int mgr_impl::helper_list_to_json( const char * lpszKey, xos_box::i_list * pList, i_json * pRoot )
    {
        int ret = 0;

        xos_box::i_variant * pVT = 0;
        i_json * pJson = 0;

        if( 0 == ret )
        {
            ret = create( &pJson );
        }

        for( pList->reset(); ( 0 == ret ) && ( pVT = ( xos_box::i_variant * )pList->next() ); )
        {
            xos_box::i_variant::VT_TYPE vType = pVT->get_type( 0 );
            switch( vType )
            {
            case xos_box::i_variant::VT_STRING:
                {
                    pJson->append_str( pVT->str() );
                }
                break;
            case xos_box::i_variant::VT_DOUBLE:
                {
                    pJson->append_double( pVT->dbl() );
                }
                break;
            case xos_box::i_variant::VT_FLOAT:
                {
                    pJson->append_double( pVT->flt() );
                }
                break;
            case xos_box::i_variant::VT_INT:
                {
                    pJson->append_int( pVT->it() );
                }
                break;
            case xos_box::i_variant::VT_OBJECT:
                {
                    obj_to_json( lpszKey, pVT, pJson );
                }
                break;
            default:
                {
                    pJson->append_str( "unknown" );
                }
                break;
            }
        }

        if( 0 == ret )
        {
            pRoot->set_json( lpszKey, pJson );
        }

        xos_stl::release_interface( pJson );

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // pack to string
    // 
    int mgr_impl::pack( i_json * pv, char * lpszStr, int nLen, int * pnLenRet )
    {
        int nRet = 0;

        json_impl * pJson = ( json_impl * )pv;
        std::string str;

        if( 0 == nRet )
        {
            Json::FastWriter writer;
            str = writer.write( pJson->m_value );
        }

        if( ( 0 == nRet ) && ( (int)str.length() >= nLen ) )
        {
            nRet = 1;
        }

        if( ( 0 == nRet ) && lpszStr )
        {
            g_pSysData->m_pContainer->crt()->strcpy( lpszStr, nLen, str.c_str() );
        }

        if(pnLenRet )
        {
            *pnLenRet = ( int )str.length();
        }

        return nRet;
    }

    // 
    // parse
    // 
    int mgr_impl::parse( const char * lpszStr, int nLen, i_json ** ppv )
    {
        int nRet = 0;

        json_impl * pJson = 0;

        if( 0 == nRet )
        {
            pJson = json_impl::get_item_from_pool( true );
            pJson->init();
        }

        if( 0 == nRet )
        {
            Json::Reader reader;
            bool bRet = reader.parse( lpszStr, lpszStr + nLen, pJson->m_value, false );
            if( !bRet )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            *ppv = ( i_json * )pJson;
            pJson = 0;
        }

        if( pJson )
        {
            pJson->release();
            pJson = 0;
        }

        return nRet;
    }

    // 
    // create node
    // 
    int mgr_impl::create( i_json ** ppv )
    {
        int nRet = 0;

        json_impl * p = json_impl::get_item_from_pool( true );
        p->init();
        *ppv = p;

        return nRet;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr_impl::put_back_to_pool( T * pT, bool bLock )
    {
        int ret = 0;
        delete this;
        return ret;
    }

    int mgr_impl::init()
    {
        int ret = 0;
        return ret;
    }

    int mgr_impl::term()
    {
        int ret = 0;
        return ret;
    }

} // xos_json
